﻿Imports System.Xml
Imports System.Net
Imports System.Drawing
Imports System.Web

Namespace Data

    Public Enum Units
        Standard = 1
        Metric = 2
    End Enum

    Public Enum IconTypes
        Png = 1
        Gif = 2
    End Enum

    Public Module Provider

        Public Function GetCurrentConditions(ByVal location As String, ByVal partnerID As String, ByVal key As String, ByVal units As Data.Units) As Object
            Try
                Dim cc As CurrentConditions
                Dim cacheKey As String = String.Format("CurrentConditions-{0}", location.ToUpper)
                If HttpContext.Current.Cache(cacheKey) Is Nothing Then
                    Dim url As String = "http://xoap.weather.com/weather/local/{0}"
                    Dim xd As New XmlDocument
                    Dim wc As New WebClient
                    Dim n0 As XmlNode
                    Dim nl As XmlNode
                    Dim n2 As XmlNode
                    Dim u As String

                    Select Case units
                        Case Data.Units.Standard
                            u = "s"
                        Case Data.Units.Metric
                            u = "m"
                        Case Else
                            u = "s"
                    End Select

                    wc.QueryString.Add("par", partnerID)
                    wc.QueryString.Add("key", key)
                    wc.QueryString.Add("link", "xoap")
                    wc.QueryString.Add("prod", "xoap")
                    wc.QueryString.Add("cc", "*")
                    wc.QueryString.Add("unit", u)

                    Dim xml As String = wc.DownloadString(String.Format(url, location))
                    xd.LoadXml(xml)

                    If xd.GetElementsByTagName("error").Count > 0 Then
                        Dim err As New ServiceError
                        Dim errN As XmlNode = xd.GetElementsByTagName("err")(0)
                        err.Code = errN.Attributes("type").InnerText
                        err.Description = errN.InnerText
                        wc.Dispose()
                        Return err
                    End If

                    n0 = xd.GetElementsByTagName("head")(0)
                    nl = xd.GetElementsByTagName("cc")(0)
                    n2 = xd.GetElementsByTagName("loc")(0)

                    cc = New CurrentConditions

                    If n0.ChildNodes.Count > 0 Then
                        cc.UnitTemperature = n0.Item("ut").InnerText
                        cc.UnitDistance = n0.Item("ud").InnerText
                        cc.UnitSpeed = n0.Item("us").InnerText
                        cc.UnitPrecipitation = n0.Item("ur").InnerText
                        cc.UnitPresure = n0.Item("up").InnerText
                    End If

                    If nl.ChildNodes.Count > 0 Then
                        cc.LastUpdate = GetDateFromLSUP(nl.Item("lsup").InnerText)
                        cc.Temperature = GetIntegerFromString(nl.Item("tmp").InnerText)
                        cc.RealFealTemperature = GetIntegerFromString(nl.Item("flik").InnerText)
                        cc.Description = CleanResourceString(nl.Item("t").InnerText)
                        cc.Icon = GetIcon(nl.Item("icon").InnerText)
                        cc.Pressure = GetDecimalFromString(nl.Item("bar").Item("r").InnerText)
                        cc.PressureDescription = GetPresureIcon(nl.Item("bar").Item("d").InnerText)
                        cc.WindSpeed = GetIntegerFromString(nl.Item("wind").Item("s").InnerText)
                        cc.WindDirection = GetIntegerFromString(nl.Item("wind").Item("d").InnerText)
                        cc.WindDirectionDescription = nl.Item("wind").Item("t").InnerText
                        cc.RelativeHumidity = GetIntegerFromString(nl.Item("hmid").InnerText)
                        cc.Visiblity = GetDecimalFromString(nl.Item("vis").InnerText)
                        cc.UVIndex = GetIntegerFromString(nl.Item("uv").Item("i").InnerText)
                        cc.UVDescription = CleanResourceString(nl.Item("uv").Item("t").InnerText)
                        cc.DewPoint = GetIntegerFromString(nl.Item("dewp").InnerText)
                        cc.MoonIcon = GetIcon(nl.Item("moon").Item("icon").InnerText)
                        cc.MoonDescription = CleanResourceString(nl.Item("moon").Item("t").InnerText)
                    Else
                        cc.Icon = GetIcon("NA")
                    End If

                    If n2.ChildNodes.Count > 0 Then
                        cc.Location = n2.Item("dnam").InnerText.Split(",")(0)
                        cc.Sunrise = GetTimeFromString(n2.Item("sunr").InnerText)
                        cc.Sunset = GetTimeFromString(n2.Item("suns").InnerText)
                        cc.Longitude = GetDecimalFromString(n2.Item("lon").InnerText)
                        cc.Latitude = GetDecimalFromString(n2.Item("lat").InnerText)
                    End If

                    wc.Dispose()
                    HttpContext.Current.Cache.Insert(cacheKey, cc, Nothing, Now.AddMinutes(25), Nothing)
                Else
                    cc = HttpContext.Current.Cache(cacheKey)
                End If

                Return cc
            Catch ex As Exception
                Dim err As New ServiceError
                err.Code = 0
                err.Description = String.Format(My.Resources.Weather.UnexpectedError, ex.Message.ToString)
                Return err
            End Try
        End Function

        Public Function GetForecast(ByVal location As String, ByVal partnerID As String, ByVal key As String, ByVal units As Data.Units, ByVal length As Int16) As Object
            Try
                Dim fc As Forecast
                Dim cacheKey As String = String.Format("Forecast-{0}", location.ToUpper)
                If HttpContext.Current.Cache(cacheKey) Is Nothing Then
                    Dim url As String = "http://xoap.weather.com/weather/local/{0}"
                    Dim xd As New XmlDocument
                    Dim wc As New WebClient
                    Dim n0 As XmlNode
                    Dim nl As XmlNode
                    Dim n2 As XmlNode
                    Dim u As String

                    Select Case units
                        Case Data.Units.Standard
                            u = "s"
                        Case Data.Units.Metric
                            u = "m"
                        Case Else
                            u = "s"
                    End Select

                    If length < 1 Then length = 1
                    If length > 5 Then length = 5

                    wc.QueryString.Add("par", partnerID)
                    wc.QueryString.Add("key", key)
                    wc.QueryString.Add("link", "xoap")
                    wc.QueryString.Add("prod", "xoap")
                    wc.QueryString.Add("cc", "*")
                    wc.QueryString.Add("unit", u)
                    wc.QueryString.Add("dayf", length)

                    Dim xml As String = wc.DownloadString(String.Format(url, location))
                    xd.LoadXml(xml)

                    If xd.GetElementsByTagName("error").Count > 0 Then
                        Dim err As New ServiceError
                        Dim errN As XmlNode = xd.GetElementsByTagName("err")(0)
                        err.Code = errN.Attributes("type").InnerText
                        err.Description = errN.InnerText
                        wc.Dispose()
                        Return err
                    End If

                    n0 = xd.GetElementsByTagName("head")(0)
                    nl = xd.GetElementsByTagName("loc")(0)
                    n2 = xd.GetElementsByTagName("dayf")(0)

                    fc = New Forecast

                    If n0.ChildNodes.Count > 0 Then
                        fc.UnitTemperature = n0.Item("ut").InnerText
                        fc.UnitDistance = n0.Item("ud").InnerText
                        fc.UnitSpeed = n0.Item("us").InnerText
                        fc.UnitPrecipitation = n0.Item("ur").InnerText
                        fc.UnitPresure = n0.Item("up").InnerText
                    End If

                    If nl.ChildNodes.Count > 0 Then
                        fc.Location = nl.Item("dnam").InnerText.Split(",")(0)
                    End If

                    If n2.ChildNodes.Count > 0 Then
                        fc.LastUpdate = GetDateFromLSUP(n2.Item("lsup").InnerText)
                    End If

                    For Each dn As XmlNode In n2.ChildNodes
                        If dn.Name = "day" Then
                            Dim part As XmlNodeList = dn.SelectNodes("part")

                            Dim day As New ForecastDay
                            day.Name = CleanResourceString(dn.Attributes("t").InnerText.Trim)
                            day.MaxTemperature = GetIntegerFromString(dn.Item("hi").InnerText)
                            day.MinTemperature = GetIntegerFromString(dn.Item("low").InnerText)
                            day.Sunrise = GetTimeFromString(dn.Item("sunr").InnerText)
                            day.Sunset = GetTimeFromString(dn.Item("suns").InnerText)
                            day.DayIcon = GetIcon(part(0).Item("icon").InnerText)
                            day.DayDescription = CleanResourceString(part(0).Item("t").InnerText)
                            day.DayWindSpeed = GetIntegerFromString(part(0).Item("wind").Item("s").InnerText)
                            day.DayWindDirection = GetIntegerFromString(part(0).Item("wind").Item("d").InnerText)
                            day.DayWindDirectionDescription = part(0).Item("wind").Item("t").InnerText
                            day.DayPrecipitation = GetIntegerFromString(part(0).Item("ppcp").InnerText)
                            day.DayRelativeHumidity = GetIntegerFromString(part(0).Item("hmid").InnerText)
                            day.NightIcon = GetIcon(part(1).Item("icon").InnerText)
                            day.NightDescription = CleanResourceString(part(1).Item("t").InnerText)
                            day.NightWindSpeed = GetIntegerFromString(part(1).Item("wind").Item("s").InnerText)
                            day.NightWindDirection = GetIntegerFromString(part(1).Item("wind").Item("d").InnerText)
                            day.NightWindDirectionDescription = part(1).Item("wind").Item("t").InnerText
                            day.NightPrecipitation = GetIntegerFromString(part(1).Item("ppcp").InnerText)
                            day.NightRelativeHumidity = GetIntegerFromString(part(1).Item("hmid").InnerText)

                            fc.Days.Add(day)
                        End If
                    Next

                    wc.Dispose()
                    HttpContext.Current.Cache.Insert(cacheKey, fc, Nothing, Now.AddMinutes(210), Nothing)
                Else
                    fc = HttpContext.Current.Cache(cacheKey)
                End If

                Return fc
            Catch ex As Exception
                Dim err As New ServiceError
                err.Code = 0
                err.Description = String.Format(My.Resources.Weather.UnexpectedError, ex.Message.ToString)
                Return err
            End Try
        End Function

        Private Function GetDateFromLSUP(ByVal lsup As String) As DateTime
            Dim s As String() = lsup.Replace("Local Time", String.Empty).Trim.Split(" ")
            Dim s1 As String() = s(0).Split("/")
            Dim s2 As String() = s(1).Split(":")
            Dim d As New DateTime(String.Format("{0}{1}", DateTime.Now.Year.ToString.Substring(0, 2), s1(2)), s1(0), s1(1), s2(0), s2(1), 0)

            If s(2).ToString.Trim = "PM" Then d = d.AddHours(12)

            Return d
        End Function

        Private Function GetTimeFromString(ByVal str As String) As DateTime
            Dim s1 As String() = str.Trim.Split(" ")
            Dim s2 As String() = s1(0).Split(":")

            Dim d As New DateTime(Now.Year, Now.Month, Now.Day, s2(0), s2(1), 0)

            If s1(1).ToString.Trim = "PM" Then d = d.Add(New TimeSpan(12, 0, 0))

            Return d
        End Function

        Private Function GetDecimalFromString(ByVal s As String) As Decimal
            s = s.Replace(".", Globalization.NumberFormatInfo.CurrentInfo.NumberDecimalSeparator).Trim
            Dim d As Decimal = 0
            Decimal.TryParse(s, d)
            Return d
        End Function

        Private Function GetIntegerFromString(ByVal s As String) As Integer
            Dim i As Integer = 0
            Integer.TryParse(s, i)
            Return i
        End Function

        Private Function CleanResourceString(ByVal str As String) As String
            Try
                Return str.Replace("/", String.Empty).Replace(" ", String.Empty).Trim
            Catch ex As Exception
                Return str
            End Try
        End Function

        Private Function GetIcon(ByVal icon As String) As String
            Dim s As String = icon.ToString.Trim
            If s.Length = 1 Then s = String.Format("0{0}", s)
            Return s
        End Function

        Private Function GetPresureIcon(ByVal desc As String) As String
            Return String.Format("Pressure{0}", StrConv(desc.Trim.ToLower, VbStrConv.ProperCase))
        End Function

        Public Function GetDirectionResource(ByVal tekst As String) As String
            tekst = tekst.Trim.ToUpper
            If tekst.Length = 0 Then Return String.Empty

            Dim s As String = String.Empty
            Select Case tekst
                Case "VAR", "CALM"
                    s = My.Resources.Weather.ResourceManager.GetString(String.Format("Direction{0}", tekst))
                Case Else
                    For Each n As Char In tekst
                        s &= My.Resources.Weather.ResourceManager.GetString(String.Format("Direction{0}", n))
                    Next
            End Select

            Return s
        End Function

    End Module

End Namespace

